package logic;

import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.LocalDevice;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;

/**
 * class for awaiting for servers in a thread
 * @author Rekin
 *
 */
public class BtClientConnection{

	//this UUID determines our application - server will look for such service
	private final String serviceUUID = LogicHelper.serviceUUID;
	private final String connectionParameters = 
		";authorize=false;authenticate=false;encrypt=false";
	
	private LocalDevice localDevice;
	private StreamConnectionNotifier notifier;
	private String localName;
	private int previousDiscoverable;
	private AcceptAndOpenThread th;
	private boolean btError;
	private boolean canceled;
	
	/**
	 * default constructor
	 */
	public BtClientConnection() {
		try{
			btError=false;
			canceled=false;
			previousDiscoverable=-1;
			localDevice = LocalDevice.getLocalDevice();
			localName = localDevice.getFriendlyName();
			previousDiscoverable=localDevice.getDiscoverable();
			localDevice.setDiscoverable(DiscoveryAgent.GIAC);
		}
		catch(BluetoothStateException e){
			btError=true;
		}
		catch(Exception e){
			btError=true;
		}
		
		th=new AcceptAndOpenThread();
		th.start();
	}
	
	/**
	 * method called in the end, after server connects to us
	 * @param con Bluetooth connection
	 */
	public void connectionDiscoveryFinished(BluetoothConnection con){
		if(canceled){
			return;
		}
		if(con==null){
			connectionNotEstablished();
		}
		else{
			connectionEstablished(new BluetoothConnection[]{con});
		}
	}
	
	/**
	 * method for canceling awaiting for connection from server
	 * @param wasCanceled indicates if user canceled by clicking the button
	 */
	public void stopBt(boolean wasCanceled){
		try{
			localDevice.setDiscoverable(previousDiscoverable);
		}
		catch(Exception e){}
		canceled=wasCanceled;
	}
	
	/**
	 * information when connection couldn't be established
	 */
	public void connectionNotEstablished(){
		stopBt(false);
		Alert errPop = LogicHelper.makePopup("Error",
				"Unable to establish connection", 3000, AlertType.ERROR);
		MainMidlet.getMidletInstance().showClientServerSelectScreen();
		MainMidlet.getMidletInstance().setDisplay(errPop);
	}
	
	/**
	 * method called when connection was successfully established
	 * @param connections table of active connections
	 */
	public void connectionEstablished(BluetoothConnection[] connections){
		MainMidlet.getMidletInstance().setBluetoothCommunicationHandler(
				new BluetoothCommunicationHandler(connections, false));
		MainMidlet.getMidletInstance().startMultiplayerBluetoothGame();
		
	}
	
	/**
	 * shuts down the application notifier
	 */
	synchronized private void closeNotifier(){
		if(notifier!=null){
			try{
				notifier.close();
			}
			catch(Exception e){}
			notifier=null;
		}
	}
	
	/**
	 * private thread class for block and wait for server connection
	 * @author Rekin
	 *
	 */
	private class AcceptAndOpenThread extends Thread{
		public void run(){
			BluetoothConnection btCon=null;
			if(!btError){
				try{
					if(localName.length()==0){
						localName="Unknown";
					}
					final String connectorOpenString =
						"btspp://localhost:" + serviceUUID + ";name=" + localName + connectionParameters;
					notifier = (StreamConnectionNotifier) Connector.open(connectorOpenString);
					StreamConnection streamCon=(StreamConnection)notifier.acceptAndOpen(); //blocking
					btCon=new BluetoothConnection(streamCon, localName, "Host");
					String playerName=MainMidlet.getTempSettings().getPlayerName();
					//send my name to server
					btCon.writeString(playerName); 
				}
				catch(Exception e){
					System.out.println("notifier stream exception: "+e.getMessage());
					btCon=null;
				}
			}
			closeNotifier();
			connectionDiscoveryFinished(btCon);
		}
	}
}
